// phalanx vector_type_traits.hpp.cu header file

// Copyright (c) 2010 - 2011 Kohei Takahashi (Flast).
// Distributed under the MIT license. for more detail see COPYING.

#ifndef IG_PHALANX_TYPE_TRAITS_DETAIL_VECTOR_TYPE_TRAITS_HPP_CU_ONCE_
#define IG_PHALANX_TYPE_TRAITS_DETAIL_VECTOR_TYPE_TRAITS_HPP_CU_ONCE_

#include <phalanx/config.hpp.cu>

#include <cstddef>

#include <vector_types.h>

#include <boost/preprocessor/repeat.hpp>
#include <boost/preprocessor/inc.hpp>
#include <boost/preprocessor/dec.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/tuple/elem.hpp>

#include <phalanx/detail/retypedef.hpp.cu>

#include <phalanx/type_traits/detail/base_traits.hpp.cu>

namespace phalanx
{

namespace traits_detail
{

template < typename T >
struct vector_type_traits
  : public base_traits< T >
{
    PHALANX_PP_RETYPEDEF( base_traits< T >, size_type );
    static const size_type size_value = 1;

    PHALANX_CONFIG_DEFAULT_FUNCTION( true )
    static size_type
    size( void )
    { return size_value; }
};

#define VECTOR_TYPE_TRAITS_IMPL( _unused_z, elnum, type_pair ) \
  template <> \
  struct vector_type_traits< \
    BOOST_PP_CAT( \
      BOOST_PP_TUPLE_ELEM( 2, 0, type_pair ), \
      BOOST_PP_INC( elnum ) ) > \
    : public base_traits< BOOST_PP_TUPLE_ELEM( 2, 1, type_pair ) > \
  { \
      PHALANX_PP_RETYPEDEF( \
        base_traits< BOOST_PP_TUPLE_ELEM( 2, 1, type_pair ) >, size_type ); \
      static const size_type size_value = BOOST_PP_INC( elnum ); \
      \
      PHALANX_CONFIG_DEFAULT_FUNCTION( true ) \
      static size_type \
      size( void ) \
      { return size_value; } \
  };

#define VECTOR_TYPE_TRAITS_IMPL_I( dim, type ) \
  VECTOR_TYPE_TRAITS_IMPL( 0, BOOST_PP_DEC( dim ), type )

#define VECTOR_TYPE_TRAITS_IMPL_R( max_dim, type ) \
  BOOST_PP_REPEAT( max_dim, VECTOR_TYPE_TRAITS_IMPL, type )

#define VECTOR_TYPE_TRAITS_IMPL_Z( max_dim, type ) \
  VECTOR_TYPE_TRAITS_IMPL_R( max_dim, \
    (        BOOST_PP_TUPLE_ELEM( 2, 0, type ), \
      signed BOOST_PP_TUPLE_ELEM( 2, 1, type ) ) ); \
  VECTOR_TYPE_TRAITS_IMPL_R( max_dim, \
    ( BOOST_PP_CAT( u, BOOST_PP_TUPLE_ELEM( 2, 0, type ) ), \
      unsigned         BOOST_PP_TUPLE_ELEM( 2, 1, type ) ) )

VECTOR_TYPE_TRAITS_IMPL_Z( 4, (     char,      char ) );
VECTOR_TYPE_TRAITS_IMPL_Z( 4, (    short,     short ) );
VECTOR_TYPE_TRAITS_IMPL_Z( 4, (      int,       int ) );
VECTOR_TYPE_TRAITS_IMPL_Z( 4, (     long,      long ) );
VECTOR_TYPE_TRAITS_IMPL_Z( 4, ( longlong, long long ) );

VECTOR_TYPE_TRAITS_IMPL_R( 4, (  float,  float ) );
VECTOR_TYPE_TRAITS_IMPL_R( 4, ( double, double ) );

VECTOR_TYPE_TRAITS_IMPL_I( 3, ( dim, unsigned int ) );

#undef VECTOR_TYPE_TRAITS_IMPL_Z
#undef VECTOR_TYPE_TRAITS_IMPL_R
#undef VECTOR_TYPE_TRAITS_IMPL_I
#undef VECTOR_TYPE_TRAITS_IMPL

} // namespace traits_detail

} // namespace phalanx

#endif // IG_PHALANX_TYPE_TRAITS_DETAIL_VECTOR_TYPE_TRAITS_HPP_CU_ONCE_

